package com.shinhye.mobilelottery.utils;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.HashMap;

public class SoftMap<K, V> extends HashMap<K, V> {
	private static final long serialVersionUID = 3937813408797588664L;
	private HashMap<K, MySoftRefer<V>> temp;
	private ReferenceQueue<V> queue;
	
	public SoftMap() {
		temp = new HashMap<K, MySoftRefer<V>>();
		queue = new ReferenceQueue<V>();
	}
	
	@Override
	//因为没有执行super.put，所以该SoftMap的方法只能重写了才能用
	public V put(K key, V value) {
		//当引用的目标对象value被GC回收时，会向queue中把sr加进去。
		MySoftRefer<V> sr = new MySoftRefer<V>(key, value, queue);
		temp.put(key, sr);
		return null;
	}
	
	@Override
	public V get(Object key) {
		clearNullSoftReference();
		MySoftRefer<V> sr = temp.get(key);
		if(sr != null) {
			return sr.get();
		}
		return null;
	}
	
	@Override
	public boolean containsKey(Object key) {
		clearNullSoftReference();
		MySoftRefer<V> sr = temp.get(key);
		if(sr != null) {
			if(sr.get() != null)
				return true;
		}
		return false;
	}
	
	private void clearNullSoftReference() {
		MySoftRefer<V> sr = (MySoftRefer<V>) queue.poll();
		while(sr != null) {
			temp.remove(sr.key);
			sr =  (MySoftRefer<V>) queue.poll();
		}
	}
	
	private class MySoftRefer<T> extends SoftReference<T> {
		Object key;
		public MySoftRefer(Object key, T r, ReferenceQueue<? super T> q) {
			super(r, q);
			this.key = key;
		}
	}
}
